home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / g / gnu_c / gempp19.zoo / gem++19 / src / gemf.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-30  |  7.5 KB  |  364 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10.  
  11. #include <aesbind.h>
  12. #include <vdibind.h>
  13. #include <values.h>
  14. #include "gemf.h"
  15. #include "gemo.h"
  16. #include "geme.h"
  17. #include "gemr.h"
  18. #include "flyform.h"
  19. #include "grect.h"
  20.  
  21.  
  22. GEMform::GEMform(const GEMrsc& in, int RSCindex) :
  23.     myindex(RSCindex),
  24.     ZoomOn(FALSE),
  25.     flight(TRUE),
  26.     open(0)
  27. {
  28.     Obj=in.Tree(myindex);
  29.     AlignObject(ROOT,1,1);
  30. }
  31.  
  32. static int global_count;
  33. static GEMrawobject* global_obj;
  34. static int CountObj(GEMrawobject* o, int i) { global_count++; return -1; }
  35.  
  36. // Why is "foo=bar" different from "foo=GEMrawobject(bar)"?
  37. static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=GEMrawobject(o[i]); return -1; }
  38. //static int CopyObj(GEMrawobject* o, int i) { global_obj[i]=o[i]; return -1; }
  39.  
  40. GEMform::GEMform(const GEMform& copy) :
  41.     myindex(copy.myindex),
  42.     ZoomOn(copy.ZoomOn),
  43.     flight(copy.flight),
  44.     xoffset(copy.xoffset),
  45.     yoffset(copy.yoffset),
  46.     xmult(copy.xmult),
  47.     ymult(copy.ymult),
  48.     open(0)
  49. {
  50.     global_count=0;
  51.  
  52.     // CountObj doesn't modify copy, so safe to cast off constness
  53.     ((GEMform&)copy).Map(CountObj,FALSE);
  54.  
  55.     Obj=new GEMrawobject[global_count];
  56.     global_obj=Obj;
  57.  
  58.     ((GEMform&)copy).Map(CopyObj,FALSE);
  59. }
  60.  
  61. GEMform::~GEMform()
  62. {
  63. }
  64.  
  65. static int FindEdit(GEMrawobject* o, int i)
  66. {
  67.     return o[i].Editable() ? i : -1;
  68. }
  69.  
  70. int GEMform::FormDo()
  71. {
  72.     int edit=Map(FindEdit,TRUE);
  73.     return form_do(Obj,edit);
  74. }
  75.  
  76. int GEMform::Do()
  77. {
  78.     int x,y,w,h;
  79.     form_center(Obj,&x,&y,&w,&h);
  80.     return Do(x,y);
  81. }
  82.  
  83. int GEMform::Do(int x, int y)
  84. {
  85.     open++; // Not actually re-entrant yet.
  86.  
  87.     // I have not used the GEM++ VDI class here, because that
  88.     // would drag all that functionality in.  When gemlib gets a
  89.     // bit more stable, I will use the GEM++ VDI.
  90.     int j;
  91.     int WorkOut[64];
  92.     int WorkIn[]={1,1,1,1,1,1,1,1,1,1,2};
  93.     vdihandle=graf_handle(&j,&j,&j,&j);
  94.     v_opnvwk(WorkIn,&vdihandle,WorkOut);
  95.  
  96.     int X,Y,w,h;
  97.  
  98.     int bx,by,bw,bh;
  99.     wind_get(0,WF_WORKXYWH,&bx,&by,&bw,&bh);
  100.  
  101.     // We use form_center, because it accounts for outline width.
  102.     form_center(Obj,&X,&Y,&w,&h);
  103.  
  104.     if (w < bw) { // Can't do anything if it fills the width
  105.         // We cancel the "centering" effect - just need w.
  106.         Obj[ROOT].MoveBy(x-X,0);
  107.  
  108.         // Then, align the object tree, AND adjust the save-area/clip accordingly.
  109.         int dx=(Obj[ROOT].X()+xoffset+xmult/2)/xmult*xmult-xoffset-Obj[ROOT].X();
  110.         x+=dx;
  111.         Obj[ROOT].MoveBy(dx,0);
  112.  
  113.         // But... make sure it is within the root window (if possible without resizing)
  114.         if (x+w > bx+bw) {
  115.             // Off right side - flushright.
  116.             dx=(bx+bw)-(x+w);
  117.         } else if (x<bx) {
  118.             // Off left side - flushleft.
  119.             dx=bx-x;
  120.         } else {
  121.             dx=0;
  122.         }
  123.  
  124.         x+=dx;
  125.         Obj[ROOT].MoveBy(dx,0);
  126.     }
  127.  
  128.     if (h < bh) { // Can't do anything if it fills the height
  129.         // Then we cancel the "centering" effect - just need (w,h).
  130.         Obj[ROOT].MoveBy(0,y-Y);
  131.  
  132.         // Then, align the object tree, AND adjust the save-area/clip accordingly.
  133.         int dy=(Obj[ROOT].Y()+yoffset+ymult/2)/ymult*ymult-yoffset-Obj[ROOT].Y();
  134.         Obj[ROOT].MoveBy(0,dy);
  135.         y+=dy;
  136.  
  137.         // But... make sure it is within the root window (if possible without resizing)
  138.         if (y+h > by+bh) {
  139.             dy=(by+bh)-(y+h);
  140.         } else if (y<by) {
  141.             dy=by-y;
  142.         } else {
  143.             dy=0;
  144.         }
  145.  
  146.         y+=dy;
  147.         Obj[ROOT].MoveBy(0,dy);
  148.     }
  149.  
  150.     wind_update(BEG_UPDATE);
  151.  
  152.     if (ZoomOn) form_dial(FMD_GROW,0,0,0,0,x,y,w,h);
  153.  
  154.     if (flight) {
  155.         flybuffer = flysave(vdihandle,x,y,w,h);
  156.     } else {
  157.         flybuffer = 0;
  158.     }
  159.  
  160.     if (!flybuffer) form_dial(FMD_START,0,0,0,0,x,y,w,h);
  161.  
  162.     objc_draw(Obj, ROOT, MAX_DEPTH, x, y, w, h);
  163.  
  164.     GEMfeedback NowWhat=ContinueInteraction;
  165.     int exitor=0;
  166.  
  167.     while (NowWhat!=EndInteraction) {
  168.         // The guts of the interaction is virtual
  169.         exitor=FormDo();
  170.  
  171.         // But the response handling is not... until the DoItem().
  172.         if (exitor != -1) {
  173.             exitor&=0x7fff; // Ignore the "TOUCHEXIT double click" bit for now.
  174.  
  175.             if (Obj[exitor].Exit()) Obj[exitor].Deselect();
  176.  
  177.             GEMevent e; // Current mouse state.
  178.             NowWhat=DoItem(exitor,e);
  179.  
  180.             if (NowWhat==IgnoredClick && Obj[exitor].Exit())
  181.                 NowWhat=EndInteraction;
  182.         } else {
  183.             NowWhat=EndInteraction;
  184.         }
  185.     }
  186.  
  187.     if (flybuffer) {
  188.         flyrestore(flybuffer);
  189.         flybuffer=0;
  190.     } else {
  191.         form_dial(FMD_FINISH,0,0,0,0,x,y,w,h);
  192.     }
  193.  
  194.     if (ZoomOn)
  195.         form_dial(FMD_SHRINK,0,0,0,0,
  196.             Obj[ROOT].X(),Obj[ROOT].Y(),Obj[ROOT].Width(),Obj[ROOT].Height()
  197.         );
  198.  
  199.     wind_update(END_UPDATE);
  200.  
  201.     v_clsvwk(vdihandle);
  202.     vdihandle=-1;
  203.  
  204.     open--;
  205.  
  206.     return exitor;
  207. }
  208.  
  209. void GEMform::RedrawObject(int RSCindex)
  210. {
  211.     if (IsOpen()) {
  212.         objc_draw(Obj,RSCindex,MAX_DEPTH,0,0,MAXSHORT,MAXSHORT);
  213.     }
  214. }
  215.  
  216. void GEMform::RedrawObjectFromRoot(int RSCindex)
  217. {
  218.     int X,Y;
  219.     objc_offset(Obj,RSCindex,&X,&Y);
  220.     RedrawObject(ROOT,X-Obj[ROOT].X(),Y-Obj[ROOT].Y(),Obj[RSCindex].Width(),Obj[RSCindex].Height());
  221. }
  222.  
  223. void GEMform::RedrawObject(int RSCindex,int Cx,int Cy,int Cw,int Ch) // Clipped
  224. {
  225.     if (IsOpen()) {
  226.         int X,Y;
  227.         objc_offset(Obj,RSCindex,&X,&Y);
  228.         objc_draw(Obj,RSCindex,MAX_DEPTH,Cx+X,Cy+Y,Cw,Ch);
  229.     }
  230. }
  231.  
  232. int GEMform::Parent(int o) const
  233. {
  234.     int n=o;
  235.  
  236.     do {
  237.         o=n;
  238.         n=Obj[n].Next();
  239.     } while (n>=0 && Obj[n].Tail()!=o);
  240.  
  241.     return n;
  242. }
  243.  
  244. void GEMform::AlignObject(int RSCindex, int xmlt=8, int ymlt=1)
  245. {
  246.     int x,y;
  247.     objc_offset(Obj,RSCindex,&x,&y);
  248.  
  249.     int rx,ry;
  250.     objc_offset(Obj,ROOT,&rx,&ry);
  251.  
  252.     xoffset=x-rx;
  253.     yoffset=y-ry;
  254.     xmult=xmlt;
  255.     ymult=ymlt;
  256. }
  257.  
  258. /* Non-recursive traverse of an object tree. */
  259. int GEMform::Map(int Do(GEMrawobject*, int), bool skiphidden, int RSCfrom, int RSCto)
  260. {
  261.     int tmp = RSCfrom;        // Initialize to impossible value
  262.  
  263.     // Look until final node, or off
  264.     // the end of tree
  265.     while (RSCfrom != RSCto && RSCfrom >= 0) {
  266.         // Did we 'pop' into RSCfrom node for the second time?
  267.         // Is this subtree hidden?
  268.         if (Obj[RSCfrom].Tail() == tmp
  269.          || (skiphidden && Obj[RSCfrom].HideTree())) {
  270.             // Yes - move right.
  271.             tmp = RSCfrom;
  272.             RSCfrom = Obj[tmp].Next();
  273.         } else {
  274.             // No, this is a new node
  275.             tmp = RSCfrom;
  276.             RSCfrom = -1;
  277.  
  278.             // Apply operation
  279.             int reply=Do(Obj, tmp);
  280.  
  281.             // Found object to return?
  282.             if (reply>=0) return reply;
  283.  
  284.             // Traverse subtree?
  285.             if (reply==-1) RSCfrom = Obj[tmp].Head();
  286.  
  287.             // Traverse right if nowhere to go
  288.             if (RSCfrom < 0)
  289.                 RSCfrom = Obj[tmp].Next();
  290.         }
  291.     }
  292.  
  293.     return -1;
  294. }
  295.  
  296. GEMfeedback GEMform::DoItem(int obj, const GEMevent& e)
  297. {
  298.     GEMfeedback result=IgnoredClick;
  299.  
  300.     // CallBacks
  301.     GEMobject* O=operator[](obj).Cook();
  302.  
  303.     if (O) {
  304.         int ox,oy;
  305.         objc_offset(Obj,obj,&ox,&oy);
  306.         result=O->Touch(e.X()-ox,e.Y()-oy,e);
  307.  
  308.         switch (result) {
  309.          case RedrawMe:
  310.             RedrawObject(obj);
  311.         break; case RedrawMyParent:
  312.             RedrawObject(Parent(obj));
  313.         break; default: ;
  314.         }
  315.     }
  316.  
  317.     return result;
  318. }
  319.  
  320. bool GEMform::Flight(bool on)
  321. {
  322.     bool result=flight;
  323.     flight=on;
  324.     return result;
  325. }
  326.  
  327. void GEMform::Fly(bool opaque)
  328. {
  329.     if (flight && flybuffer && vdihandle>=0) {
  330.         int dx,dy;
  331.         flyfly(vdihandle,&flybuffer,&dx,&dy,opaque);
  332.         Obj[ROOT].MoveBy(dx,dy);
  333.         if (!opaque) {
  334.             // Must redraw in this case
  335.             RedrawObject(0);
  336.         }
  337.     }
  338. }
  339.  
  340. bool GEMform::IsOpen()
  341. {
  342.     return open>0;
  343. }
  344.  
  345. GRect* GEMform::FirstClip(int RSCobject)
  346. {
  347.     if (IsOpen()) {
  348.         GRect* result=new GRect;
  349.         objc_offset(Obj,RSCobject,&result->g_x,&result->g_y);
  350.         result->g_w=Obj[RSCobject].Width();
  351.         result->g_h=Obj[RSCobject].Height();
  352.         // XXX Should we also clip to screen border?
  353.         return result;
  354.     } else {
  355.         return 0;
  356.     }
  357. }
  358.  
  359. GRect* GEMform::NextClip(GRect* prev)
  360. {
  361.     delete prev;
  362.     return 0;
  363. }
  364.